﻿using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace ETask.Api.Data
{
    public class JwtAuthenticationMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly IConfiguration _configuration;

        public JwtAuthenticationMiddleware(RequestDelegate next, IConfiguration configuration)
        {
            _next = next;
            _configuration = configuration;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            var token = context.Request.Headers.Authorization.FirstOrDefault()?.Substring("Bearer ".Length).Trim();
            if (token != null)
            {
                try
                {
                    var userInfo = ValidateJwtToken(token);
                    if (userInfo != null)
                    {
                        UserContext.CurrentUser = userInfo;
                    }
                }
                catch (Exception ex)
                {
                    context.Response.StatusCode = 401;
                    await context.Response.WriteAsync("Invalid token");
                    return;
                }
            }
            await _next(context);
            UserContext.Clear();
        }

        private LoginUser ValidateJwtToken(string token)
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            var key = Encoding.ASCII.GetBytes(_configuration["Jwt:Key"]);

            try
            {
                tokenHandler.ValidateToken(token, new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(key),
                    ValidateIssuer = false,
                    ValidateAudience = false,
                    ClockSkew = TimeSpan.Zero
                }, out SecurityToken validatedToken);

                var jwtToken = (JwtSecurityToken)validatedToken;
                return new LoginUser
                {
                    Id = int.Parse(jwtToken.Claims.First(x=>x.Type.Equals(ClaimTypes.NameIdentifier)).Value),
                    Name = jwtToken.Claims.First(x=>x.Type.Equals(ClaimTypes.Name)).Value,
                    Account = jwtToken.Claims.First(x => x.Type == "account").Value
                };
            }
            catch
            {
                return null;
            }
        }
    }
}
